#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from fastapi import (
    Depends, Header, HTTPException, Request
)
from fastapi.security import OAuth2PasswordBearer
from typing import Optional
import jwt

from core.ctx import CTX_USER_ID
from settings.config import settings
from common.exception.errors import CustomException
from utils.jwt_util import JWTUtil

from app.admin.model import Role, User, Api
from app.admin.enums import SysUserEnum

class CustomOAuth2PasswordBearer(OAuth2PasswordBearer):
    async def __call__(self, request: Request) -> Optional[str]:
        try:
            # 调用父类的 __call__ 方法提取 Token
            return await super().__call__(request)
        except HTTPException:
            # 自定义异常信息
            raise HTTPException(
                status_code=401,
                detail="未授权",
                headers={"WWW-Authenticate": "Bearer"},
            )

oauth2_scheme = CustomOAuth2PasswordBearer(
    tokenUrl=f"{settings.API_V1_STR}/login/access-token"
)

class AuthControl:
    @classmethod
    async def is_authed(cls, token: str = Depends(oauth2_scheme)) -> Optional[User]:
        if token is None:
            raise CustomException(code=401, msg="缺少Token")
        try:
            if token == "dev":
                user = await User.filter().first()
                user_id = user.id
            else:
                if token.startswith('Bearer'):
                    token = token.split(' ')[1]
                decode_data = JWTUtil.decode_dict(token)
                user_id = decode_data.get("user_id")
            user = await User.filter(id=user_id).first()
            if not user:
                raise CustomException(code=401, msg="授权失败")
            CTX_USER_ID.set(int(user_id))
            return user
        except jwt.DecodeError:
            raise CustomException(code=401, msg="无效的Token")
        except jwt.ExpiredSignatureError:
            raise CustomException(code=401, msg="登录已过期")
        except HTTPException as e:
            raise
        except Exception as e:
            raise CustomException(code=500, msg=f"{repr(e)}")
        
class PermissionControl:
    @classmethod
    async def has_permission(cls, request: Request, current_user: User = Depends(AuthControl.is_authed)) -> None:
        
        if current_user.user_type == SysUserEnum.SUPERUSER.value:
            return
        method = request.method
        path = request.url.path
        roles: list[Role] = await current_user.roles
        if not roles:
            raise HTTPException(status_code=403, detail="用户未绑定角色")
        apis = [await role.apis for role in roles]
        permission_apis = list(set((api.method, api.path) for api in sum(apis, [])))
        if (method, path) not in permission_apis:
            raise HTTPException(status_code=403, detail=f"接口无权限:{method} 路径:{path}")
        
DependPermisson = Depends(PermissionControl.has_permission)